//
//  ASCollectionNode-selector.swift
//  soapp
//
//  Created by zhu xietong on 2018/4/24.
//

import Foundation
import UIKit
import Eelay
import AsyncDisplayKit


//extension TP {
//    public typealias selector = [String:Any]
//    public typealias section = [[[String:Any]]]
//    public typealias options = [[String:Any]]
//}
//




extension ASCollectionNode {
    private struct AssociatedKeys {
        static var model = "model_key"
        static var cell_selector = "cell_selectors_key"
    }
    
    
    public func load(sections:TP.section=TP.section(),selector:TP.selector)
    {
        if sections.count == 0{
            let section1:TP.section = [[]]
            let model =  CellSelector.createModel(sections: section1)
            self.model =  model
        }
        else
        {
            let model =  CellSelector.createModel(sections: sections)
            self.model =  model
            if let mview = self.view as? MoAtrributeProtocol
            {
                mview.mo.model = model
            }
        }
        
        self.cell_selector = selector
    }
    
    
    
    var cell_selector: TP.selector? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.cell_selector) as? [String:AnyObject]
        }
        set {
            if let newValue = newValue {
                
                objc_setAssociatedObject(self, &AssociatedKeys.cell_selector, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
    
    
    public var model: NSMutableDictionary {
        get {
            if let obj = objc_getAssociatedObject(self, &AssociatedKeys.model) as? NSMutableDictionary
            {
                return obj
            }
            let obj = NSMutableDictionary()
            self.model = obj
            return obj
            
        }
        set {
            
            //            self.willLoad(model: newValue)
            if (objc_getAssociatedObject(self, &AssociatedKeys.model) as? NSMutableDictionary) != nil
            {
                //                self.willReleaseModel(old:obj)
            }
            
            objc_setAssociatedObject(self, &AssociatedKeys.model, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            //            self.loadModelContent()
        }
    }
    
    
    
}


private struct NodeKeys {
    static var nodeType = "__cellNodeType__"
}




extension ASCollectionNode{
    
    public func headerData(at section:Int) -> NSMutableDictionary?
    {
        
        if let header = self.model[obj:"headers.section\(section)",nil] as? NSMutableDictionary
        {
            return header
        }
        return nil
    }
    
    public func cellData(at indexPath:IndexPath) -> NSMutableDictionary?
    {
        if let section_data = self.model["section\(indexPath.section)"] as? NSMutableArray
        {
            if section_data.count > indexPath.row
            {
                
                if let cell_data = section_data[indexPath.row] as? NSMutableDictionary
                {
                    cell_data["__row__"] = "\(indexPath.row)"
                    cell_data["__section__"] = "\(indexPath.section)"
                    return cell_data
                }
                return nil
            }
        }
        return nil
    }
    
    public func sectionCount()->Int
    {
        return self.model.allKeys.count
    }
    
    public func cellCount(section:Int)->Int
    {
        if let sectionInfo = self.model["section\(section)"] as? NSMutableArray
        {
            return sectionInfo.count
        }
        return 0
    }
    
    
    static public func cellNodeType(data:NSMutableDictionary,indexPath:IndexPath,selector:TP.selector) -> ASCellNode.Type? {
        if let cellID = CellSelector.cellTypeIdentify(indexPath: indexPath, item: data, selector: selector)
        {
            return selector[cellID] as? ASCellNode.Type
        }
        return nil
    }
    
    

    
    @objc public func cellNode(indexPath:IndexPath,fillModel:Bool=true,delegate:JoTableCellDelegate?=nil) ->ASCellNode
    {
        if let data = self.cellData(at: indexPath)
        {
            guard let NodeType = ASCollectionNode.cellNodeType(data: data, indexPath: indexPath, selector: cell_selector!) else{
//                print("can not get NodeType for model:\(data)")
                fatalError("can not get Cell NodeType for model:\(data)")
            }

//            print("______)_",delegate)
            let cellNode = NodeType.init()
            if let mnode = cellNode as? MoAtrributeProtocol
            {

                if let jo_cell = cellNode as? JoCellNode{
                    if let t = delegate as? MoDisplayNode{
                        jo_cell.mo.controller = t.mo.controller

                    }
                    if let t = delegate as? JoCellNode{
                        jo_cell.mo.controller = t.mo.controller
                    }
                    jo_cell.mo.controller = delegate as? UIViewController
                    jo_cell.delegate = delegate
                }
                
                mnode.mo.model = data
            }
            return cellNode
        }
        let cellNode = ASCellNode()
        return cellNode
    }
    
  
    
    
    public func cellBlock(indexPath:IndexPath,fillModel:Bool=true,delegate:JoTableCellDelegate?=nil,nodeBuild:@escaping (ASCellNode)->Void) ->(block:ASCellNodeBlock,node:ASCellNode?)
    {
        if let data = self.cellData(at: indexPath)
        {
            
            weak var node:ASCellNode?
            guard let NodeType = ASCollectionNode.cellNodeType(data: data, indexPath: indexPath, selector: cell_selector!) else{
                fatalError()
            }
            
            let cellNodeBlock = { () -> ASCellNode in
                let cellNode = NodeType.init()
                if let jo_cell = cellNode as? JoCellNode{
                    jo_cell.mo.controller = delegate as? UIViewController
                    jo_cell.delegate = delegate
                }
                if let mnode = cellNode as? MoAtrributeProtocol
                { 
                    mnode.mo.model = data
                }
                node = cellNode
                nodeBuild(cellNode)
                return cellNode
            }
            return (cellNodeBlock,node)
        }
        
        let block = { () -> ASCellNode in
            let cellNode = ASCellNode()
            return cellNode
        }
        return (block,nil)
        
    }
}


extension ASCollectionNode{
    static public func headerNodeType(data:NSMutableDictionary,section:Int,selector:TP.selector) -> ASCellNode.Type? {
        if let headID = CellSelector.headerIdentify(section: section, item: data, selector: selector)
        {
            return selector[headID] as? ASCellNode.Type
        }
        return nil
    }
    
    
    func headerNode(section:Int,fillModel:Bool=true,delegate:JoTableCellDelegate?=nil) ->ASCellNode
    {
        if let data = self.headerData(at: section)
        {
            guard let NodeType = ASCollectionNode.headerNodeType(data: data, section: section, selector: cell_selector!) else{
                //                print("can not get NodeType for model:\(data)")
                fatalError("can not get Header NodeType for model:\(data)")
            }
           
            let cellNode = NodeType.init()
            
            if let mnode = cellNode as? MoAtrributeProtocol
            {
                if let jo_cell = cellNode as? JoCellNode{
                    jo_cell.mo.controller = delegate as? UIViewController
                    jo_cell.delegate = delegate
                }
                mnode.mo.model = data

            }
            return cellNode
        }
        let cellNode = ASCellNode()
        return cellNode
    }
    
    func headerSize(section:Int,fillModel:Bool=true,delegate:JoTableCellDelegate?=nil) ->ASSizeRange
    {
        var size = ASSizeRange(min: .zero, max: .zero)
        if let data = self.headerData(at: section)
        {

            if data["hidden","NO"] == "YES"
            {
                return ASSizeRange(min: .zero, max: .zero)
            }
            
            guard let NodeType = ASCollectionNode.headerNodeType(data: data, section: section, selector: cell_selector!) else{
                //                print("can not get NodeType for model:\(data)")
                fatalError("can not get Header Size for model:\(data)")
            }
            if let cellNode = NodeType.init() as? ASSizeRangeCell{
//                cellNode.delegate = delegate
                cellNode.mo.controller = delegate as? UIViewController
//                cellNode.mo.model = data;
                size = cellNode.sizeRange()
            }
        }
        return size
    }
    
}



